package cn.tedu.core;


import cn.tedu.vo.BeanDefinition;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 基于xml文件来存储核心对象的容器类
 * @author Kiven
 */
public class ClassPathXMLApplicationContext {

    /**
     * 核心上下文配置文件路径
     */
    private volatile String contextConfigLocation;
    /**
     * 实例map
     */
    private Map<String,Object> instanceMap = new HashMap<>();
    /**
     * 管理bean定义信息的map
     */
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    public ClassPathXMLApplicationContext(){
        this.contextConfigLocation = "classpath:spring.xml";
        // 此方法用于初始化bean定义map
        initBeanMap();
        // 以上完成后,把非懒加载的对象放入instanceMap中

    }

    /**
     * 读取xml文件信息把他赋值给BeanDefinition然后再存入BeanDefinitionMap中
     * 把非懒加载的对象放入instanceMap中
     */
    public ClassPathXMLApplicationContext(String path){
        this.contextConfigLocation=path;
        // 此方法用于初始化bean定义map
        // 完成后,把非懒加载的对象放入instanceMap中
        initBeanMap();
    }

    private void initBeanMap() {
        InputStream in = getClass().getClassLoader().getResourceAsStream(contextConfigLocation);
        // 在此之前,请去pom.xml添加dom4j依赖
       try{
           SAXReader saxReader = new SAXReader();
           Document doc = saxReader.read(in);
           Element rootElement = doc.getRootElement();

           List<Element> elements = rootElement.elements();
           for (Element e:elements) {
               String id = e.attributeValue("id");
               Boolean lazy = Boolean.parseBoolean(e.attributeValue("lazy"));
               String pageClass = e.attributeValue("pageClass");
               BeanDefinition beanDefinition = new BeanDefinition(id,lazy,pageClass);
               beanDefinitionMap.put(id,beanDefinition);
               if(!lazy){
                   //通过反射实例对象,然后在添加到实例map中
                   Object o = newInstance(pageClass);
                   instanceMap.put(id,o);
               }
           }

           System.out.println("bean定义map:"+ beanDefinitionMap);
           System.out.println("bean实例map:"+instanceMap);

       }catch (Exception e){
           e.printStackTrace();
       }
    }

    private Object newInstance(String pageClass){
        try {
            Class<?> aClass = Class.forName(pageClass);
            Object o = aClass.newInstance();
            return o;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public Object getBean(String key){
        // 先判断bean实例map是否存在
        Object o = instanceMap.get(key);
        if(o==null){
            // 再判断定义map中有没有
            BeanDefinition beanDefinition = beanDefinitionMap.get(key);
            if(beanDefinition!=null){
                o=newInstance(beanDefinition.getPageClass());
                instanceMap.put(beanDefinition.getId(),o);
            }
        }
        return o;
    }

    public <T>T getBean(String key,Class<T> tClass){
        Object bean = getBean(key);
        return (T)bean;
    }

    public static void main(String[] args) {
        ClassPathXMLApplicationContext ac = new ClassPathXMLApplicationContext("beans.xml");
        Object date1 = ac.getBean("date1");
        //Date date11 = ac.getBean("object1", Date.class);
        System.out.println(date1);
       // System.out.println(date11);
    }

}
